from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List

from loguru import logger

from mdtool.commands.base_command import Command
from mdtool.commands.check_md_format_command import CheckFormatForAllCommand
from mdtool.commands.feisu_command import SaveToFeiShuCommand
from mdtool.config_reader import Config
from mdtool.markdown_document import MarkdownDocument
from mdtool.publish.wx_publisher import WxPublisher
from mdtool.util import is_valid_dir
from mdtool.wx_cache import WxCache
from mdtool.wx_client import WxClient


class CheckModifiedCommand(Command):
    """检查 7 天内创建或修改过的所有Markdown 文件格式的命令"""

    def execute(self, config: Config, **kwargs) -> bool:
        articledir = config.get(Config.ARTICLE_DIR)
        if not articledir or not is_valid_dir(articledir):
            logger.error(f"无效的源目录：{articledir}")
            return False

        md_files = list(Path(articledir).glob("**/*.md"))
        if not md_files:  # 当前目录为空时，只发出一个警告，不中断程序
            logger.warning(f"目录 {articledir} 中没有找到 markdown 文件")
            return True
        # 找到最近的 7 天内创建或修改过的 md 文件列表
        seven_days_ago = datetime.now() - timedelta(days=7)
        recent_md_files = []
        for md_file in md_files:
            stat = md_file.stat()
            mtime = datetime.fromtimestamp(stat.st_mtime)
            ctime = datetime.fromtimestamp(stat.st_ctime)
            if mtime >= seven_days_ago or ctime >= seven_days_ago:
                recent_md_files.append(md_file)
        md_files = recent_md_files

        invalid_files = []
        for md_file in md_files:
            relative_path = Path(md_file).relative_to(articledir)
            try:
                md_doc = MarkdownDocument.from_file(str(relative_path), articledir)
                ret = md_doc.check_format()
                if len(ret) > 0:
                    logger.warning(f"文件格式错误 {md_file}: {ret}")
                    invalid_files.append(str(md_file))
            except Exception as e:
                logger.error(f"检查文件出错 {md_file}: {e}")
                invalid_files.append(str(md_file))

        total_files = len(md_files)
        print("-" * 10)
        print(f"七天内共修改了 {total_files} 个文件。")
        if not invalid_files:
            print("全部文件格式合格。")
        else:
            print(f"格式有错误的共有：{len(invalid_files)}")
            print("不合格列表如下：")
            for file in invalid_files:
                print(f"\t{file}")
        return True


def is_draft_file(file_path):
    try:
        with open(file_path, "r", encoding="utf-8") as f:
            for _ in range(30):  # 只检查前30行
                line = f.readline()
                if not line:
                    break
                if "draft" in line.lower() and '"false"' in line.lower():
                    return False
            return True
    except Exception as e:
        logger.error(f"读取文件 {file_path} 时出错: {e}")
        return False


class PublishCommand(Command):
    """发布文章到微信公众号的命令"""

    def execute(self, config: Config, **kwargs) -> bool:
        cache = WxCache(config)
        wx_publisher = WxPublisher(cache, config)
        articledir = config.get(Config.ARTICLE_DIR)

        if not articledir or not is_valid_dir(articledir):
            logger.error(f"无效的源目录：{articledir}")
            return False

        pathlist = list(Path(articledir).glob("**/*.md"))
        total_count = len(pathlist)
        filtered_pathlist = [path for path in pathlist if not is_draft_file(path)]

        draft_count = len(filtered_pathlist)
        draft_files = [path for path in pathlist if path not in filtered_pathlist]
        if total_count == 0:
            print("md 文件总数: 0")
            return False
        if total_count == draft_count:
            print(f"md 文件总数: {total_count}, 全部是 draft。")

        cached_files = []
        success_files = []
        failed_files = []

        for path in filtered_pathlist:
            if cache.is_cached(str(path)):
                logger.debug(f"{str(path)} 已处理")
                cached_files.append(str(path))
                continue

            relative_path = Path(path).relative_to(articledir)
            md_doc = MarkdownDocument.from_file(str(relative_path), articledir)
            media_id = wx_publisher.publish_single_article(md_doc)
            if media_id:
                logger.info(f"上传成功：{str(path)}")
                success_files.append(str(path))
            else:
                logger.error(f"上传失败：{str(path)}")
                failed_files.append(str(path))

        print(f"md 文件总数: {total_count if total_count else '0'}")
        print(f"草稿数量: {len(draft_files) if draft_files else '0'}")
        print(f"已处理过的数据: {len(cached_files) if cached_files else '0'}")
        print(
            f"新上传成功的数量: {len(success_files) if success_files else '0'}", end=""
        )
        if len(success_files) > 0:
            print(", 文件名:")
            for f in success_files:
                print(f"\t{f}")
        else:
            print("")
        print(f"上传失败的数量: {len(failed_files) if failed_files else '0'}", end="")
        if len(failed_files) > 0:
            print(", 文件名:")
            for f in failed_files:
                print(f"\t{f}")
        else:
            print("")
        print("-" * 20)
        print("Task：清理无用的重复图片。")
        cache.remove_duplication(cache.find_cached_imgs_with_duplication())
        return True


class ImageListCommand(Command):
    """获取公众号图片列表的命令"""

    def execute(self, config: Config, **kwargs) -> bool:
        wx_client = WxClient(config)
        result = wx_client.get_image_list()
        print(result.to_json())
        print("-" * 10)
        print(f"total_count: \t{result.total_count}")
        return True


class DraftListCommand(Command):
    """获取草稿列表的命令"""

    def execute(self, config: Config, is_draft: bool = True, **kwargs) -> bool:
        articledir = config.get(Config.ARTICLE_DIR)
        if not articledir or not is_valid_dir(articledir):
            logger.error(f"无效的源目录：{articledir}")
            return False

        pathlist = list(Path(articledir).glob("**/*.md"))
        draft_list = []
        if is_draft:
            draft_list = [path for path in pathlist if is_draft_file(path)]
            print(f"文件总数: {len(pathlist)}")
            print(f"草稿总数: {len(draft_list)}")
            return True
        else:
            ready_list = [path for path in pathlist if path not in draft_list]
            print(f"文件总数: {len(pathlist)}")
            print(f"已完成总数: {len(ready_list)}")
        return True


class RemoveDuplicateCommand(Command):
    """删除重复图片的命令"""

    def execute(self, config: Config, **kwargs) -> bool:
        cache = WxCache(config)
        articledir = config.get(Config.ARTICLE_DIR)
        if not articledir or not is_valid_dir(articledir):
            logger.error(f"无效的源目录：{articledir}")
            return False

        cache.remove_duplication(cache.find_cached_imgs_with_duplication())
        return True


class AtCommander:
    """命令执行器，负责管理和执行所有命令"""

    def __init__(self, config: Config):
        self._commands: Dict[str, Command] = {
            "check": CheckModifiedCommand(),
            "checkall": CheckFormatForAllCommand(),
            "publish": PublishCommand(),
            "imglist": ImageListCommand(),
            "draft": DraftListCommand(),
            "nodraft": DraftListCommand(),
            "rm_dup": RemoveDuplicateCommand(),
            "save_to_feishu": SaveToFeiShuCommand(),
        }
        self.config = config

    def execute(self, action: str, config: Config, **kwargs) -> bool:
        if action not in self._commands:
            logger.error(f"未知的命令：{action}")
            return False

        command = self._commands[action]
        is_draft = True if action == "draft" else False
        return command.execute(config, is_draft=is_draft, **kwargs)

    def get_available_commands(self) -> List[str]:
        """获取所有可用的命令列表"""
        return list(self._commands.keys())
